namespace Guia.Elements
{
    using System;
    using System.Diagnostics.Contracts;
    using System.Windows.Automation;
    using Guia.Core;
    using Guia.Locator;

    /// <summary>
    /// This is an abstract super class for all TreeView related classes
    /// </summary>
    public abstract class AbstractTreeView : UiElement
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="AbstractTreeView"/> class.
        /// </summary>
        /// <param name="automationElement">
        /// The automation element.
        /// </param>
        protected AbstractTreeView(AutomationElement automationElement) : base(automationElement)
        {
        }

        /// <summary>
        /// Gets all direct TreeViewItems of this element.
        /// </summary>
        public virtual TreeViewItem[] Items
        {
            get
            {
                SearchCondition searchCondition = SearchCondition.FromAutomationCondition(Condition.TrueCondition);
                searchCondition.Scope = TreeScope.Children;
                return this.GetAll<TreeViewItem>(searchCondition);
            }
        }

        /// <summary>
        /// Gets the TreeViewItem with the given name (Header value).
        /// </summary>
        /// <param name="itemName">
        /// The name (Header) of the TreeViewItem.
        /// </param>
        /// <exception cref="ArgumentNullException">This exception is thrown if the itemName is null.</exception>
        public virtual TreeViewItem this[string itemName]
        {
            get
            {
                return this.GetItem(itemName);
            }
        }

        /// <summary>
        /// Gets the TreeViewItem at the given position.
        /// </summary>
        /// <param name="index">The index of the desired TreeViewItem.</param>
        /// <returns>The TreeViewItem at the given position.</returns>
        /// <exception cref="ElementNotFoundException">This exception is thrown if no TreeViewItem exist at the given position.</exception>
        /// <exception cref="ArgumentOutOfRangeException">This exception is thrown if index if out of range.</exception>"
        public TreeViewItem this[int index]
        {
            get
            {
                return this.GetItem(index);
            }
        }

        /// <summary>
        /// Gets the TreeViewItem with the given name (Header value).
        /// </summary>
        /// <param name="itemName">
        /// The name (Header) of the TreeViewItem.
        /// </param>
        /// <returns>
        /// The TreeViewItem with the given name (Header value).
        /// </returns>
        /// <exception cref="ArgumentNullException">This exception is thrown if the itemName is null.</exception>
        public virtual TreeViewItem GetItem(string itemName)
        {
            Contract.Requires<ArgumentNullException>(itemName != null);
            return this.GetByName<TreeViewItem>(itemName);
        }

        /// <summary>
        /// Gets the TreeViewItem at the given position.
        /// </summary>
        /// <param name="index">The index of the desired TreeViewItem.</param>
        /// <returns>The TreeViewItem at the given position.</returns>
        /// <exception cref="ElementNotFoundException">This exception is thrown if no TreeViewItem exist at the given position.</exception>
        public TreeViewItem GetItem(int index)
        {
            Contract.Requires<ArgumentOutOfRangeException>(index >= 0 && index < this.Items.Length);
            try
            {
                TreeViewItem[] items = this.Items;
                TreeViewItem item = items[index];

                return item;
            }
            catch (IndexOutOfRangeException)
            {
                throw new ElementNotFoundException("No TreeViewItem found with the index " + index);
            }
        }
    }
}